﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Windows;
using System.Collections.ObjectModel;

namespace OpenFrameworkCore.Controls
{
    /// <summary>
    /// OpenFramework에서 Control을 그룹화할때 사용하는 Control
    /// </summary>
	public class BasicGroupControl : BasicControl
    {
		/// <summary>
		/// GroupControl이 관리하는 Control의 Name List
		/// </summary>
		public static readonly DependencyProperty ManagedControlNameListProperty = DependencyProperty.Register
			(
			"ManagedControlNameList",
			typeof(ObservableCollection<string>),
			typeof(BasicGroupControl),
			new PropertyMetadata(OnManagedControlNameListPropertyChanged)
			);

		private static void OnManagedControlNameListPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			((BasicGroupControl)d).OnManagedControlNameListPropertyChanged(e);
		}

		private void OnManagedControlNameListPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			ObservableCollection<string> oldValue = (ObservableCollection<string>)e.OldValue;
			ObservableCollection<string> newValue = (ObservableCollection<string>)e.NewValue;

			// 기존 값 제거
			if (oldValue != null)
			{
				oldValue.Clear();

				oldValue.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ManagedControlCollectionChanged);
			}

			if (newValue != null)
			{
				foreach (string targetControlName in newValue)
				{
					// Find Control
					ControlBase targetControl = (ControlBase)OwnerControlContainer.FindName(targetControlName);

					// If can't find target control
					// throw exception
					if (targetControl == null)
						throw new ControlException("대상 Control을 찾을 수 없습니다. Control 이름: " + targetControl.Name);

					OnControlAdded(targetControl);
				}

				newValue.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ManagedControlCollectionChanged);
			}
		}

		public ObservableCollection<string> ManagedControlNameList
		{
			get
			{
				return (ObservableCollection<string>)GetValue(ManagedControlNameListProperty);
			}

			private set
			{
				SetValue(ManagedControlNameListProperty, value);
			}
		}

		/// <summary>
		/// ControlContext 오버라이딩
		/// </summary>
		public override ControlBaseContext ControlContext
		{
			get
			{
				return base.ControlContext;
			}
			set
			{
				base.ControlContext = value;
			}
		}

		/// <summary>
		/// Binding 초기화
		/// </summary>
		protected override void InitBinding()
		{
			base.InitBinding();

			// ManagedControlNameList binding 설정
			Binding managedControlNameListBinding = new Binding("ManagedControlNameList");
			managedControlNameListBinding.Source = ControlContext;
			managedControlNameListBinding.Mode = BindingMode.TwoWay;
			SetBinding(ManagedControlNameListProperty, managedControlNameListBinding);
		}

		/// <summary>
		/// Binding 제거
		/// </summary>
		protected override void ClearBinding()
		{
			base.ClearBinding();

			ClearValue(ManagedControlNameListProperty);
		}

		/// <summary>
		/// 생성자
		/// </summary>
		public BasicGroupControl()
		{
			ManagedControlNameList = new ObservableCollection<string>();
		}

        /// <summary>
        /// GroupItemControl을 추가합니다.
        /// </summary>
		public void AddControlToGroup(ControlBase targetControl)
        {
			string controlName = targetControl.Name;

			// 이미 Control이 포함되어 있는 경우
			if (ManagedControlNameList.Contains(controlName))
				throw new DuplicateControlException("이미 그룹에 포함되어 있는 Control입니다");

			// 이미 Control이 다른 Group에 포함되어 있는 경우
			if (targetControl.OwnerGroupID != null)
				throw new DuplicateControlException("이미 타그룹에 속해 있는 Control입니다.");

			// List에 Control 추가
			ManagedControlNameList.Add(controlName);
        }

        /// <summary>
        /// GroupItemControl을 제거합니다.
        /// </summary>
        public void RemoveControlFromGroup(ControlBase targetControl)
        {
			if (ManagedControlNameList.Contains(targetControl.Name) == false)
				throw new ControlException("그룹에 속해 있지 않은 Control입니다.");

			// List에서 Control 제거
			ManagedControlNameList.Remove(targetControl.Name);
        }

		/// <summary>
		/// Group에 포함된 Control이 변경된 경우 호출되는 메서드
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void ManagedControlCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
			{
				foreach (string targetControlName in e.NewItems)
				{
					// Find Control
					ControlBase targetControl = (ControlBase)OwnerControlContainer.FindName(targetControlName);

					// If can't find target control
					// throw exception
					if (targetControl == null)
						throw new ControlException("대상 Control을 찾을 수 없습니다. Control 이름: " + targetControl.Name);

					// Owner Group ID 부여
					targetControl.OwnerGroupID = this.Name;

					OnControlAdded(targetControl);
				}
			}

			else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
			{
				foreach (string targetControlName in e.OldItems)
				{
					// Find Control
					ControlBase targetControl = (ControlBase)OwnerControlContainer.FindName(targetControlName);

					// If can't find target control
					// throw exception
					if (targetControl == null)
						throw new ControlException("대상 Control을 찾을 수 없습니다. Control 이름: " + targetControl.Name);

					// Owner Group ID 제거
					targetControl.OwnerGroupID = null;

					OnControlRemoved(targetControl);
				}
			}
		}

		/// <summary>
		/// Control이 추가된 경우 호출되는 메서드
		/// </summary>
		/// <param name="targetControl"></param>
		protected virtual void OnControlAdded(ControlBase targetControl)
		{
		}

		/// <summary>
		/// Control이 삭제된 경우 호출되는 메서드
		/// </summary>
		/// <param name="targetControl"></param>
		protected virtual void OnControlRemoved(ControlBase targetControl)
		{
		}
    }
}
